﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TagsViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the <seealso cref="TagsViewModel" /> type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Client.Modules.Core.Tag.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics.Contracts;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Input;
    using Business.Interfaces;
    using Common.BaseClasses;
    using Hisaab.Client.Common;
    using Hisaab.Client.Common.Services;
    using Hisaab.Client.Modules.Core.Properties;
    using Hisaab.Client.Modules.Core.Tag.Commands;
    using Hisaab.Common;
    using Microsoft.Practices.Prism;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.Regions;
    using Microsoft.Practices.ServiceLocation;
    using Model;

    /// <summary>
    /// Defines the <seealso cref="TagsViewModel"/> type.
    /// </summary>
    public class TagsViewModel : TabViewModel, INavigationAware
    {
        #region Data Members

        /// <summary>
        /// Member variable _tagManager
        /// </summary>
        private readonly ITagManager _tagManager;

        /// <summary>
        /// Member variable _selectedTag
        /// </summary>
        private Tag _selectedTag;

        /// <summary>
        /// Member variable _tags
        /// </summary>
        private ObservableCollection<Tag> _tags;

        /// <summary>
        /// Member variable _editCommand
        /// </summary>
        private ICommand _editCommand;

        /// <summary>
        /// Member variable _deleteCommand
        /// </summary>
        private ICommand _deleteCommand;

        /// <summary>
        /// Member variable refreshCommand
        /// </summary>
        private ICommand _refreshCommand;

        /// <summary>
        /// Member variable _addTagCommand
        /// </summary>
        private AddTagCommand _addTagCommand;

        #endregion Data Members

        #region Constructors and Initializers

        /// <summary>
        /// Initializes a new instance of the <see cref="TagsViewModel"/> class.
        /// </summary>
        public TagsViewModel()
            : this(ServiceLocator.Current.GetInstance<ITagManager>())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TagsViewModel"/> class.
        /// </summary>
        /// <param name="tagManager">The tag manager.</param>
        public TagsViewModel(ITagManager tagManager)
        {
            Contract.Requires<ArgumentNullException>(tagManager != null);

            _tagManager = tagManager;
            Title = "Tags";
        }

        #endregion Constructors and Initializers

        #region Properties

        /// <summary>
        /// Gets the Tags.
        /// </summary>
        public ObservableCollection<Tag> Tags
        {
            get
            {
                if (_tags == null)
                {
                    RefreshList();
                }

                return _tags;
            }

            private set
            {
                if (value != _tags)
                {
                    _tags = value;

                    RaisePropertyChangedEvent("Tags");
                }
            }
        }

        /// <summary>
        /// Gets or sets the selected tag.
        /// </summary>
        /// <value>
        /// The selected tag.
        /// </value>
        public Tag SelectedTag
        {
            get
            {
                return _selectedTag;
            }

            set
            {
                RaisePropertyChangingEvent("SelectedTag");
                _selectedTag = value;
                RaisePropertyChangedEvent("SelectedTag");
            }
        }

        /// <summary>
        /// Gets the edit command.
        /// </summary>
        protected ICommand EditCommand
        {
            get
            {
                if (_editCommand == null)
                {
                    _editCommand = new DelegateCommand(EditTag, CanEditTag);
                }

                return _editCommand;
            }
        }

        /// <summary>
        /// Gets the delete command.
        /// </summary>
        protected ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                {
                    _deleteCommand = new DelegateCommand(DeleteTag, CanDeleteTag);
                }

                return _deleteCommand;
            }
        }

        /// <summary>
        /// Gets the refresh command.
        /// </summary>
        protected ICommand RefreshCommand
        {
            get
            {
                if (_refreshCommand == null)
                {
                    _refreshCommand = new DelegateCommand(RefreshList);
                }

                return _refreshCommand;
            }
        }

        #endregion Properties

        #region Public Methods

        /// <summary>
        /// Edits the account.
        /// </summary>
        public void EditTag()
        {
            if (SelectedTag != null)
            {
                var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
                var query = new UriQuery { { "ID", SelectedTag.TagId.ToString(CultureInfo.InvariantCulture) } };
                var accountEditor = new Uri(TagModule.TagEditor + query, UriKind.Relative);
                regionManager.RequestNavigate(Regions.SecondaryRegion, accountEditor);
            }
        }

        /// <summary>
        /// Deletes the account.
        /// </summary>
        public void DeleteTag()
        {
            if (SelectedTag != null)
            {
                var messageService = ServiceLocator.Current.GetInstance<IMessageBoxService>();
                var session = ServiceLocator.Current.GetInstance<ISession>();

                var result = messageService.Show(
                    session.Application.MainWindow,
                    Resources.Message_Tag_Delete_Confirmation,
                    Resources.ApplicationName,
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Question);
                if (result == MessageBoxResult.Yes)
                {
                    _tagManager.Delete(SelectedTag.Map<Tag, Business.Entities.Tag>());
                    Tags.Remove(SelectedTag);
                }
            }
        }

        /// <summary>
        /// Determines whether this instance [can edit tag].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can edit tag]; otherwise, <c>false</c>.
        /// </returns>
        public bool CanEditTag()
        {
            return true;
        }

        /// <summary>
        /// Determines whether this instance [can delete tag] the specified obj.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can delete tag] the specified obj; otherwise, <c>false</c>.
        /// </returns>
        public bool CanDeleteTag()
        {
            return true;
        }

        /// <summary>
        /// Refreshes the list.
        /// </summary>
        public void RefreshList()
        {
            var data = _tagManager.List().Select(x => x.Map<Business.Entities.Tag, Tag>());
            Tags = new ObservableCollection<Tag>(data.ToList());
        }

        #endregion Public Methods

        #region Implementation of INavigationAware

        /// <summary>
        /// Called when [navigated to].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
            var accountRibbonTab = new Uri(TagModule.TagsTab, UriKind.Relative);
            regionManager.RequestNavigate(Regions.RibbonRegion, accountRibbonTab);

            _addTagCommand = new AddTagCommand();
            TagGlobalCommands.AddTag.RegisterCommand(_addTagCommand);
            TagGlobalCommands.EditTag.RegisterCommand(EditCommand);
            TagGlobalCommands.DeleteTag.RegisterCommand(DeleteCommand);
            TagGlobalCommands.RefreshTag.RegisterCommand(RefreshCommand);
        }

        /// <summary>
        /// Determines whether [is navigation target] [the specified navigation context].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        /// <returns>
        /// True if [is navigation target] [the specified navigation context]; otherwise, false.
        /// </returns>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        /// <summary>
        /// Called when [navigated from].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            TagGlobalCommands.AddTag.UnregisterCommand(_addTagCommand);
            TagGlobalCommands.EditTag.UnregisterCommand(EditCommand);
            TagGlobalCommands.DeleteTag.UnregisterCommand(DeleteCommand);
            TagGlobalCommands.RefreshTag.UnregisterCommand(RefreshCommand);
        }

        #endregion Implementation of INavigationAware
    }
}